package com.sky.gateway.route;


import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;

@Component
@Slf4j
@RequiredArgsConstructor
public class DynamicRouteLoader {

    private final NacosConfigManager nacosConfigManager;
    private final RouteDefinitionWriter routeDefinitionWriter;
    private String dataId = "gateway-routes.json";
    private String group = "gateway";

    private Set<String> routeIds = new HashSet<>();

    @PostConstruct //run after the class init
    public void initGateWayRouteListner() throws NacosException {
        String initRoutesConfig = nacosConfigManager.getConfigService()
                .getConfigAndSignListener(dataId, group, 5000, new Listener() {
                    @Override
                    public Executor getExecutor() {
                        return null;
                    }

                    @Override
                    public void receiveConfigInfo(String s) {
                        // update when the config changes
                        updateGatewayRoutes(s);
                    }
                });
        // the first time init
        updateGatewayRoutes(initRoutesConfig);

    }

    public void updateGatewayRoutes(String routesConfig){
        log.info("最新的路由配置：");
        log.info(routesConfig);
        List<RouteDefinition> routes = JSONUtil.toList(routesConfig, RouteDefinition.class);
        // clear the old routes
        for (String routeId : routeIds) {
            routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
        }
        routeIds.clear();
        // update the new routes
        for (RouteDefinition route : routes) {
            routeIds.add(route.getId());
            routeDefinitionWriter.save(Mono.just(route)).subscribe();
        }
    }

}
